/**
 * XaxNetCn namespace
 */
// netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
if ("undefined" == typeof(XaxNetCn)) {
	var XaxNetCn = {};
};

XaxNetCn = {

	Pages : {

		// alert switch
		bAlert : false,

		/**
		 * String to File Name
		 * 
		 * @return {}
		 */
		stringToFileName : function(aSourceString, aReplaceString) {
			// check aSourceString
			if ("undefined" == aSourceString)
				return aSourceString;
			var strRet = aSourceString;
			// default replace string is ""
			// aReplaceString which is "undefined" would be thought as false.
			var replaceString = aReplaceString ? arguments[1] : "";
			return strRet.replace(/[\\\/:*?<>""|]/g, replaceString);
		},

		pathToFileName : function(aPathName) {
			// check aPathName
			if ("undefined" == aPathName || "" == aPathName) {
				return aPathName;
			}

			// replace all the "/" to "\"
			var pathName = aPathName.replace(/\//g, "\\");
			var url = pathName.split("\\");

			// get the last url section as the file name.
			var fileName = url[url.length - 1];
			return fileName;
		},

		/**
		 * 
		 * popup on the right bottom of the screen.
		 */
		popup : function(title, msg) {
			try {
				Components.classes['@mozilla.org/alerts-service;1']
						.getService(Components.interfaces.nsIAlertsService)
						.showAlertNotification(null, title, msg, false, '',
								null);
			} catch (e) {
				// prevents runtime error on platforms that don't implement
				// nsIAlertsService
				var image = null;
				var win = Components.classes['@mozilla.org/embedcomp/window-watcher;1']
						.getService(Components.interfaces.nsIWindowWatcher)
						.openWindow(null,
								'chrome://global/content/alerts/alert.xul',
								'_blank', 'chrome,titlebar=no,popup=yes', null);
				win.arguments = [image, title, msg, false, ''];
			}
		},

		alertErr : function(e, level) {
			var defaultLevel = 0;
			if (arguments.length < 2) {
				level = defaultLevel;
			}
			this.alert(e.name + ": " + e.message);

		},

		alert : function(str) {
			if (this.bAlert) {
				alert(str);
			}
		},

		/**
		 * 转换字符串到Unicode
		 * 
		 * @param {}
		 *            str
		 * @return {}
		 */
		ConvertToUnicode : function(str) {
			var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
					.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
			this.alert("converter: " + converter);
			converter.charset = "UTF-8";
			return converter.ConvertToUnicode(str);
		},

		/**
		 * 获取document的字符集,支持IE和Firefox
		 * 
		 * @param {}
		 *            doc
		 * @return {}
		 */
		getPageCharset : function(doc) {
			var charSet = "";
			var oType = getBrowser();
			switch (oType) {
				case "IE" :
					charSet = doc.charset;
					break;
				case "FIREFOX" :
					charSet = doc.characterSet;
					break;
				default :
					break;
			}
			return charSet;
		},

		/**
		 * pickup dir using "browser.download.lastDir" as default
		 * 
		 * @param {}
		 *            aWindow
		 * @return {}
		 */
		pickupFileDir : function(aWindow) {
			const err = "";
			// check aWindow
			if (!aWindow) {
				return err;
			}
			try {
				var pref = Components.classes['@mozilla.org/preferences-service;1']
						.getService(Components.interfaces.nsIPrefBranch);
				// set browser's last download dir to fileSaveDir
				var fileSaveDir = pref.getCharPref('browser.download.lastDir');
				this.alert("Last download dir: " + fileSaveDir);

				// init file picker.
				const nsIFilePicker = Components.interfaces.nsIFilePicker;
				var filePicker = Components.classes['@mozilla.org/filepicker;1']
						.createInstance(nsIFilePicker);
				filePicker.init(aWindow, 'Chose a directory for saving files.',
						nsIFilePicker.modeGetFolder);
				// set last download dir to default.
				var fileDefaultDisplayDir = Components.classes['@mozilla.org/file/local;1']
						.createInstance(Components.interfaces.nsILocalFile);
				fileDefaultDisplayDir.initWithPath(fileSaveDir);
				filePicker.displayDirectory = fileDefaultDisplayDir;
				this.alert(filePicker.displayDirectory.path);

				// open file picker dialog
				var rv = filePicker.show();
				// get selected directory.
				if (nsIFilePicker.returnOK == rv
						|| nsIFilePicker.returnReplace == rv) {
					fileSaveDir = filePicker.file.path;
					// set the last download dir to the choosen dir.
					pref.setCharPref('browser.download.lastDir', fileSaveDir);
				}
			} catch (e) {
				this.alertErr(e);
				return err;
			}
			this.alert(fileSaveDir);

			return fileSaveDir;
		},

		/**
		 * get file name by title or pathname using title as file name default.
		 * 
		 * @param {}
		 *            title
		 * @param {}
		 *            pathname
		 * @return {}
		 */
		getFileName : function(title, pathname, fileNameSuffix) {
			if (arguments.length < 3) {
				fileNameSuffix = ".html";
			}
			var fileName = "";
			this.alert(title + pathname);
			if ("" != title) {
				// using title as file name priority
				fileName = this.stringToFileName(title, "_") + fileNameSuffix;
			} else if ("" != pathname) {
				// no title, so using pathname.
				// just like "login.jsp" or "index.html"
				var str = XaxNetCn.Pages.pathToFileName(pathname);
				fileName = XaxNetCn.Pages.stringToFileName(str);
			}
			this.alert(fileName);
			return fileName;

		},

		/**
		 * write content to file
		 * 
		 * @param {}
		 *            filePath: local file path
		 * @param {}
		 *            charset
		 * @param {}
		 *            content: string
		 */
		writeStringToFile : function(filePath, charset, content) {
			this.bAlert = false;
			this.alert("writeStringToFile: \n" + filePath + charset + content);
			var bRet = false;
			var err;
			var bErr = false;
			try {
				// create output file.
				var file = Components.classes['@mozilla.org/file/local;1']
						.createInstance(Components.interfaces.nsILocalFile);
				this.alert(file);

				file.initWithPath(filePath);
				if (file.exists())
					file.remove(false);
				file.create(file.NORMAL_FILE_TYPE, 0666);
				this.alert(file.leafName);

				// create output file stream.
				var fileStream = Components.classes['@mozilla.org/network/file-output-stream;1']
						.createInstance(Components.interfaces.nsIFileOutputStream);
				fileStream.init(file, 0x20 | 0x02 | 0x08, 0x0666, 1);

				// using nsIConverterOutputStream to write string to file.
				const nsIConvertStream = Components.interfaces.nsIConverterOutputStream;
				var converterStream = Components.classes['@mozilla.org/intl/converter-output-stream;1']
						.createInstance(nsIConvertStream);
				converterStream
						.init(
								fileStream,
								charset,
								0,
								Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
				bRet = converterStream.writeString(content);
			} catch (e) {
				bErr = true;
				err = e;
				this.alertErr(e);
			} finally {
				this.alert("finally.");
				converterStream.close();
				fileStream.close();
				if (bErr) {
					this.alert("err: " + err.name + err.message);
					throw err;
				}
				return bRet;
			}
		},

		/**
		 * change charset of document's top element
		 * 
		 * @param {}
		 *            element
		 * @param {}
		 *            charset
		 * @return {}
		 */
		changeDocumentCharset : function(element, charset) {
			try {
				var findMetaContent = false;
				var tempElement = element;
				var metas = tempElement.getElementsByTagName('meta');
				this.alert(metas.length);
				for (var i = 0; i < metas.length; i++) {
					var meta = metas[i];
					this.alert(meta);
					/*
					 * var attr = meta.getAttribute('httpEquiv'); if (attr ==
					 * 'Content-Type') { meta.setAttribute('content',
					 * "text/html; charset=" + charset);
					 * this.alert(meta.getAttribute('content'));
					 */
					this.alert(meta.httpEquiv);
					if (meta.httpEquiv.toLowerCase() == 'content-type'
							.toLowerCase()) {
						meta.content = "text/html; charset=" + charset;
						this.alert(meta.content);
						this.alert(metas[i].content);
						findMetaContent = true;
						break;
					} else {
						continue;
					}
				}
			} catch (e) {
				this.alertErr(e);
				return false;
			}
			return findMetaContent;
		},

		/**
		 * Save all the opend pages to local file. each file corresponds to a
		 * page.
		 * 
		 * @param {}
		 *            aEvent
		 */
		saveAllPages : function(aEvent) {
			this.bAlert = false;
			this.alert("Save All Opened Page, Starting...");
			var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
					.getService(Components.interfaces.nsIWindowMediator);
			this.alert(wm);
			// var browserEnumerator = wm.getEnumerator('navigator:browser');
			var recentWindow = wm.getMostRecentWindow('navigator:browser');
			this.alert(recentWindow);
			var tabbrowser = recentWindow.gBrowser;
			this.alert(tabbrowser);
			var tabNum = tabbrowser.browsers.length;
			this.alert(tabNum);

			if (tabNum < 1) {
				// no tab
				return;
			}

			// pickup download dir.
			var fileSaveDir = this.pickupFileDir(recentWindow);
			if (fileSaveDir.length < 1) {
				this.alert("invalid file save directory");
				return;
			}

			this.alert(fileSaveDir);

			var numSuccess = 0;
			var numFailure = 0;

			for (var index = 0; index < tabNum; index++) {
				var currentBrowser = tabbrowser.getBrowserAtIndex(index);
				var contentDoc = currentBrowser.contentDocument;
				var contentWindow = currentBrowser.contentWindow;
				var docWriteContent = contentDoc.documentElement.innerHTML;
				// using Document's charaset as file's charset.
				var charset = contentDoc.characterSet;
				this.alert(charset);

				// file name
				var fileName = XaxNetCn.Pages.getFileName(contentDoc.title,
						contentWindow.location.pathname);
				if ("" == fileName) {
					XaxNetCn.Pages.popup("empty page, passed.");
					numSuccess++;
					continue;
				}
				this.alert(fileName);

				// file path
				var filePath = fileSaveDir + "\\" + fileName;

				var bSaveSuccess = false;

				try {
					// write content to file.
					bSaveSuccess = XaxNetCn.Pages.writeStringToFile(filePath,
							charset, docWriteContent);
					this.alert("writeStringToFile " + bSaveSuccess);
				} catch (e) {
					this.alert("catch e");
					this.alertErr(e);
					if (e.name == 'NS_ERROR_LOSS_OF_SIGNIFICANT_DATA') {
						// processing original charset has problem, change to
						// UTF-8
						var defaultCharaset = "UTF-8";
						bSaveSuccess = XaxNetCn.Pages.changeDocumentCharset(
								contentDoc.documentElement, defaultCharaset);
						this.alert(bSaveSuccess
								+ contentDoc.documentElement.innerHTML);
						if (bSaveSuccess) {
							docWriteContent = contentDoc.documentElement.innerHTML;
							try {
								bSaveSuccess = XaxNetCn.Pages
										.writeStringToFile(filePath,
												defaultCharaset,
												docWriteContent);
							} catch (ee) {
								this.alertErr(ee);
							}
						}
					} else {
						this.alertErr(e);
					}
				}

				if (bSaveSuccess)
					numSuccess++;
				else
					numFailure++;

			}
			this.alert(numSuccess + "/" + numFailure);
			var popupTitle = "Saving " + tabNum + " Pages.";
			var popupContent = "Success " + numSuccess + ", Failure: "
					+ numFailure;
			this.popup(popupTitle, popupContent);
		}
	}
};